import './style.css'

import { J10c } from "./core/j10c";
import { F35 } from "./core/f35";
import { AudioClass } from "./core/audio";
import { Bomb } from "./core/bomb";
import { 
  getRandomFloat, 
  listenKeyboardSpace, 
  listenKeyboardArrowLeft, 
  listenKeyboardArrowRight,
  listenKeyboardArrowUp,
  listenKeyboardArrowDown,
  listenKeyboardEnter
} from "./core/unit";
import backMusic from './assets/bg4.mp3'

const GAME_STATUS_READY = Symbol("未开始");
const GAME_STATUS_STRING = Symbol("进行中");
const GAME_STATUS_OVER = Symbol("已结束");

const game = (function () {
  const dpr = window.devicePixelRatio || 1;
  const isH5 = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

  const Game: {
    canvas: HTMLCanvasElement
    ourFir: any[]
    FoeFir: any[]
    bombs: any[]
    status: any
    destoryCount: number
    [key: string] : any
  } = {
    canvas: document.querySelector("canvas") as HTMLCanvasElement,
    ourFir: [],
    FoeFir: [],
    bombs: [],
    status: GAME_STATUS_READY,
    bgAideo: null,
    destoryCount: 0,
  };


  const FirEvents = {
    onShooting: function (fir: any){
      const handel = () => fir.shooting();
      if (isH5){
        // @ts-ignore
        document.querySelector("#shoot").ontouchstart = handel;
      } else {
        // @ts-ignore
        document.querySelector("#shoot").onmousedown = handel;
      }
      const { remove } = listenKeyboardSpace(handel)
      fir.ondestory(() => {
        remove()
      })
    },
    onMoveX: function (fir: any){
      let start = 0;
      let end = 0;
      let old = 0;
      const moveHandel = (e: any) => {
        end = e.targetTouches?.[0]?.clientX || e.clientX;
        fir.position[0] = Math.min(
          fir.oriWidth - fir.width,
          Math.max(0, old + end - start)
        );
      };
      const endHandel = () => {
        if (isH5){
          Game.canvas.removeEventListener("touchmove", moveHandel);
          Game.canvas.removeEventListener("touchend", endHandel);
        }else{
          Game.canvas.removeEventListener("mousemove", moveHandel);
          Game.canvas.removeEventListener("mouseup", endHandel);
          Game.canvas.removeEventListener("mouseleave", endHandel);
        }
      };
      const startHandel = (e: any) => {
        start = e.targetTouches?.[0]?.clientX || e.clientX;
        old = fir.position[0];
        if (isH5){
          Game.canvas.addEventListener("touchmove", moveHandel);
          Game.canvas.addEventListener("touchend", endHandel);
        }else{
          Game.canvas.addEventListener("mousemove", moveHandel);
          Game.canvas.addEventListener("mouseup", endHandel);
          Game.canvas.addEventListener("mouseleave", endHandel);
        }
      };

      if (isH5){
        Game.canvas.addEventListener("touchstart", startHandel)
      } else {
        Game.canvas.addEventListener("mousedown", startHandel);
      }

      const { remove: removeArrowLeft } = listenKeyboardArrowLeft(function (){ 
        fir.position[0] = Math.min(
          fir.oriWidth - fir.width,
          Math.max(0, fir.position[0] - dpr * 4)
        );
      })
      const { remove: removeArrowRight } = listenKeyboardArrowRight(function (){ 
        fir.position[0] = Math.min(
          fir.oriWidth - fir.width,
          Math.max(0, fir.position[0] + dpr * 4)
        );
      })

      fir.ondestory(() => {
        Game.ourFir = []
        endHandel()
        removeArrowLeft()
        removeArrowRight()
        isH5 ? Game.canvas.removeEventListener("touchstart", startHandel) : Game.canvas.removeEventListener("mousedown", startHandel);
      })
    },
    onMoveY: function (fir: any) {
      let start = 0;
      let end = 0;
      let old = 0;
      const moveHandel = (e: any) => {
        end = e.targetTouches?.[0]?.clientY || e.clientY;
        fir.position[1] = Math.min(
          fir.oriHeight - fir.height,
          Math.max(0, old + end - start)
        );
      };
      const endHandel = () => {
        if(isH5){
          Game.canvas.removeEventListener("touchmove", moveHandel);
          Game.canvas.removeEventListener("touchend", endHandel);
        }else{
          Game.canvas.removeEventListener("mousemove", moveHandel);
          Game.canvas.removeEventListener("mouseup", endHandel);
          Game.canvas.removeEventListener("mouseleave", endHandel);
        }
      };
      const startHandel = (e: any) => {
        start = e.targetTouches?.[0]?.clientY || e.clientY;
        old = fir.position[1];
        if(isH5){
          Game.canvas.addEventListener("touchmove", moveHandel);
          Game.canvas.addEventListener("touchend", endHandel);
        }else{
          Game.canvas.addEventListener("mousemove", moveHandel);
          Game.canvas.addEventListener("mouseup", endHandel);
          Game.canvas.addEventListener("mouseleave", endHandel);
        }
      };

      if (isH5) {
        Game.canvas.addEventListener("touchstart", startHandel)
      } else {
        Game.canvas.addEventListener("mousedown", startHandel);
      }

      const { remove: removeArrowUp } = listenKeyboardArrowUp(function (){ 
        fir.position[1] = Math.min(
          fir.oriHeight - fir.height,
          Math.max(0, fir.position[1] - dpr * 4)
        );
      })
      const { remove: removeArrowDown } = listenKeyboardArrowDown(function (){ 
        fir.position[1] = Math.min(
          fir.oriHeight - fir.height,
          Math.max(0, fir.position[1] + dpr * 4)
        );
      })

      fir.ondestory(() => {
        Game.ourFir = []
        endHandel()
        removeArrowUp()
        removeArrowDown()
        isH5 ? Game.canvas.removeEventListener("touchstart", startHandel) : Game.canvas.removeEventListener("mousedown", startHandel);
      })
    }
  }

  function realSize() {
    const height = parseInt(window.getComputedStyle(Game.canvas).height);
    Game.canvas.width = innerWidth * dpr;
    Game.canvas.height = height * dpr;
    const context: CanvasRenderingContext2D = Game.canvas.getContext("2d") as CanvasRenderingContext2D;
    context.scale(dpr, dpr);
  }

  function createOurFir() {
    const fir = new J10c(Game.canvas);
    Game.ourFir.push(fir);
    
    FirEvents.onShooting(fir)
    FirEvents.onMoveX(fir)
    FirEvents.onMoveY(fir)

    return fir;
  }

  function createFoeFir() {
    if (document.hidden || document.visibilityState !== 'visible') return;
    
    const fir = new F35(Game.canvas);
    Game.FoeFir.push(fir);
    return fir;
  }

  function over() {
    Game.status = GAME_STATUS_OVER;
    setTimeout(() => {
      // @ts-ignore
      document.querySelector(".ready").classList.remove("hide");
    }, 1000);
  }

  function updateDestoryCount(count: number){
    Game.destoryCount = count
    document.querySelector('#count')!.innerHTML = `${count}`;
  }

  function start() {
    Game.bgAideo?.destory();
    Game.bgAideo = new AudioClass(backMusic).loop();
    Game.status = GAME_STATUS_STRING;
    Game.ourFir = []
    Game.FoeFir = []
    Game.bombs = []
    Game.destoryCount = 0
    updateDestoryCount(0);
    
    const ctx = Game.canvas.getContext("2d") as CanvasRenderingContext2D;
    
    function draw() {

      ctx.save()
      ctx.clearRect(0, 0, Game.canvas.width, Game.canvas.height);

      Game.FoeFir.forEach((fir) => {
        for (const bullet of fir.bullets) {
          // 循环红机
          for (const ourFir of Game.ourFir) {
            if (ourFir.isHit(bullet)) {
              // 销毁导弹
              fir.removeBullet(bullet);
              // 爆炸
              Game.bombs.push(new Bomb(bullet.position[0] + bullet.width / 2, bullet.position[1] + bullet.height));
              // 销毁红机
              ourFir.destory();

              // 游戏结束
              over();
            } else {
              // 画绿机导弹
              const [x, y] = bullet.position;
              ctx.fillStyle = bullet.color;
              // ctx.strokeRect(x, y, bullet.width, bullet.height)
              ctx.drawImage(bullet.image, x, y, bullet.width, bullet.height);
            }
          }
        }

        const [x, y] = fir.position;
        ctx.fillStyle = fir.color;
        ctx.drawImage(fir.image, x, y, fir.width, fir.height);
        // ctx.strokeRect(x, y, fir.width, fir.height)
      });

      Game.ourFir.forEach((fir) => {
        for (const bullet of fir.bullets) {
          // 循环敌机
          for (const foeFir of Game.FoeFir) {
            if (foeFir.isHit(bullet)) {
              fir.removeBullet(bullet);
              Game.bombs.push(new Bomb(bullet.position[0] + bullet.width / 2, bullet.position[1]));
              foeFir.destory();
              updateDestoryCount(Game.destoryCount + 1)
            } else {
              const [x, y] = bullet.position;
              ctx.fillStyle = bullet.color;
              // ctx.strokeRect(x, y, bullet.width, bullet.height)
              ctx.drawImage(bullet.image, x, y, bullet.width, bullet.height);
            }
          }
        }

        let bullets: any[] = []
        Game.FoeFir.forEach((item) => bullets = bullets.concat(item.bullets))
        fir.checkWarn(bullets)

        // 空对空
        bullets.forEach(bullet => {
          for(const ourFirBullet of fir.bullets){
            if (ourFirBullet.isHit(bullet)) {
              Game.bombs.push(new Bomb(bullet.position[0] + bullet.width / 2, bullet.position[1] + bullet.height * 0.8));
              bullet.destory()
              ourFirBullet.destory()
            }
          }
        })

        const [x, y] = fir.position;
        ctx.fillStyle = fir.color;
        // ctx.strokeRect(x, y, fir.width, fir.height)
        ctx.drawImage(fir.image, x, y, fir.width, fir.height);
      });

      Game.bombs.forEach((bomb) => {
        // @ts-ignore
        bomb.particles.forEach((particle, index) => {
          if (particle.alpha > 0) {
            particle.draw(ctx); // Draw each particle on the canvas
            particle.update();
          } else {
            bomb.particles.splice(index, 1);
          }
        });
      });

      ctx.restore();
      requestAnimationFrame(draw);
    }

    draw();
    createOurFir();
    createFirs(0);
  }

  function createFirs(delay: number) {
    if (Game.status === GAME_STATUS_OVER) return;
    setTimeout(() => {
      createFoeFir()?.commond("go");
      createFirs(getRandomFloat(0, 5000));
    }, delay);
  }

  function init() {
    // @ts-ignore
    document.body.style.opacity = 1
    realSize();
  }

  return { init, start, instance: Game };
})();

game.init();

function startHandel(){
  game.start();
  // @ts-ignore
  document.querySelector(".ready").classList.add("hide");
}

// @ts-ignore
document.querySelector("#start").onclick = startHandel
listenKeyboardEnter(startHandel)

document.addEventListener('touchmove', function(event) {
  event.preventDefault(); 
}, { passive: false });